/*
 * File Name: RepeatedField.h
 *
 * Created on: 2021-01-28
 * Author: glendy ganby@163.com
 *
 * Last Modified: 2021-01-28
 * Description:
 */

#ifndef _REPEATEDFIELD_H_
#define _REPEATEDFIELD_H_

#include <string>
#include <stdint.h>
#include "Message.h"

namespace miniproto
{
template<class T>
class RepeatedField
{
public:
	typedef ::std::vector< ::miniproto::Message* > MessageList;
	typedef ::std::vector< ::miniproto::Message* >::iterator iterator;
	typedef ::std::vector< ::miniproto::Message* >::const_iterator const_iterator;
public:
	RepeatedField();
	~RepeatedField();
	RepeatedField<T>& operator=(const RepeatedField<T>& obj);
	RepeatedField(const RepeatedField<T>& obj);
	void Destroy();
	void swap(RepeatedField<T>& obj);
	void clear();

	int size() const;
	iterator begin();
	const_iterator begin() const;
	iterator end();
	const_iterator end() const;
	void push_back(const T& obj);
	const T& at(int index) const;
	T& at(int index);
	const T& Get(int index) const;
	T& Get(int index);
	T* Add();
	void CopyFrom(const RepeatedField<T> &obj);

	MessageList &message_list();
	const MessageList &message_list() const;

private:
	MessageList message_list_;
};

template<class T>
RepeatedField<T>::RepeatedField(){}

template<class T>
RepeatedField<T>::~RepeatedField()
{
	this->Destroy();
}

template<class T>
RepeatedField<T>& RepeatedField<T>::operator=(const RepeatedField<T>& obj)
{
	this->clear();
	for (RepeatedField<T>::MessageList::iterator iter = obj.begin(); iter != obj.end(); ++iter)
	{
		this->push_back(*(*iter));
	}
	return *this;
}

template<class T>
RepeatedField<T>::RepeatedField(const RepeatedField<T>& obj)
{
	for (RepeatedField<T>::MessageList::iterator iter = obj.begin(); iter != obj.end(); ++iter)
	{
		this->push_back(*(*iter));
	}
}

template<class T>
void RepeatedField<T>::Destroy()
{
	for (RepeatedField<T>::MessageList::iterator iter = this->begin(); iter != this->end(); ++iter)
	{
		delete (*iter);
	}
	RepeatedField<T>::MessageList tmp;
	this->message_list_.swap(tmp);
}

template<class T>
void RepeatedField<T>::swap(RepeatedField<T>& obj)
{
	this->message_list_.swap(obj.message_list_);
}

template<class T>
void RepeatedField<T>::clear()
{
	for (RepeatedField<T>::MessageList::iterator iter = this->begin(); iter != this->end(); ++iter)
	{
		delete (*iter);
	}
	this->message_list_.clear();
}

template<class T>
int RepeatedField<T>::size() const
{
	return this->message_list_.size();
}

template<class T>
typename RepeatedField<T>::iterator RepeatedField<T>::begin()
{
	return this->message_list_.begin();
}

template<class T>
typename RepeatedField<T>::const_iterator RepeatedField<T>::begin() const
{
	return this->message_list_.begin();
}

template<class T>
typename RepeatedField<T>::iterator RepeatedField<T>::end()
{
	return this->message_list_.end();
}

template<class T>
typename RepeatedField<T>::const_iterator RepeatedField<T>::end() const
{
	return this->message_list_.end();
}

template<class T>
void RepeatedField<T>::push_back(const T& obj)
{
	::miniproto::Message* msg = obj.New();
	msg->MergeFrom(obj);
	this->message_list_.push_back(msg);
}

template<class T>
const T& RepeatedField<T>::at(int index) const
{
	return *(dynamic_cast<const T*>(this->message_list_.at(index)));
}

template<class T>
T& RepeatedField<T>::at(int index)
{
	return *(dynamic_cast<T*>(this->message_list_.at(index)));
}

template<class T>
const T& RepeatedField<T>::Get(int index) const
{
	return this->at(index);
}

template<class T>
T& RepeatedField<T>::Get(int index)
{
	return this->at(index);
}

template<class T>
T* RepeatedField<T>::Add()
{
	T* msg = new T();
	this->message_list_.push_back(msg);
	return msg;
}

template<class T>
void RepeatedField<T>::CopyFrom(const RepeatedField<T> &obj)
{
	this->clear();
	for (typename RepeatedField<T>::const_iterator iter = obj.begin(); iter != obj.end(); ++iter)
	{
		T* msg = this->Add();
		msg->CopyFrom(*(*iter));
	}
}

template<class T>
typename RepeatedField<T>::MessageList &RepeatedField<T>::message_list()
{
	return this->message_list_;
}

template<class T>
const typename RepeatedField<T>::MessageList &RepeatedField<T>::message_list() const
{
	return this->message_list_;
}

} // namespace miniproto

#endif //_REPEATEDFIELD_H_
